package com.debao.common.utils.wechat;

import com.debao.common.core.domain.AjaxResult;
import com.debao.common.enums.OrderTypePrefix;
import com.debao.common.utils.http.HttpUtils;
import com.debao.common.utils.uuid.IdUtils;
import com.github.wxpay.sdk.WXPayUtil;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.net.InetAddress;
import java.util.*;

public class PayUtils {

    private static final String APPID = "wx0d1179c968aa1397";
    private static final String MCHID = "1694801921";
    private static final String NOTIFY_URL = "https://api.debaoppq.cn/api/pay/callback";


    private static final String REFUND_NOTIFY_URL = "https://api.debaoppq.cn/api/refund/callback";
    private static final String KEY = "debaopingpangqiudebaopingpangqiu";


    public static String paramsFormat(String body, String outRadeNo, Long totalFee, String openId) throws Exception {
        Map<String, String> map = new HashMap<>();
        //商品描述
        map.put("body", body);
        //小程序ID
        map.put("appid", APPID);
        //商户号
        map.put("mch_id", MCHID);
        //随机字符串,长度要求在32位以内。推荐随机数生成算法
        map.put("nonce_str", WXPayUtil.generateNonceStr());
        //openid
        map.put("openid", openId);
        //商户订单号
        map.put("out_trade_no", outRadeNo);
        //标价金额
        map.put("total_fee", totalFee.toString());
        //交易类型
        map.put("trade_type", "JSAPI");
        //终端IP,APP和网页支付提交用户端ip，Native支付填调用微信支付API的机器IP。
        InetAddress localhost = InetAddress.getLocalHost();
        String hostAddress = localhost.getHostAddress();
        map.put("spbill_create_ip", hostAddress);
        //通知地址,异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。
        map.put("notify_url", NOTIFY_URL);
        //签名,通过签名算法计算得出的签名值，详见签名生成算法
        String signValue = WXPayUtil.generateSignature(map, KEY);
        map.put("sign", signValue);
        try {
            return prePay(WXPayUtil.mapToXml(map));
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 退款参数格式化
     * @param transactionId
     * @param totalFee
     * @param refundDesc
     * @return
     * @throws Exception
     */
    public static String paramsRefundFormat(String transactionId,Long totalFee, String refundDesc) throws Exception {
        Map<String, String> map = new HashMap<>();
        map.put("appid", APPID);
        map.put("mch_id", MCHID);
        map.put("nonce_str", WXPayUtil.generateNonceStr());
        map.put("transaction_id", transactionId);
        map.put("out_refund_no",  OrderTypePrefix.R + "-" + IdUtils.getC(null));
        map.put("total_fee", totalFee.toString());
        map.put("refund_fee", totalFee.toString());
        map.put("notify_url", REFUND_NOTIFY_URL);
        map.put("refund_desc", refundDesc);
        String signValue = WXPayUtil.generateSignature(map, KEY);
        map.put("sign", signValue);
        try {
            return preRefund(WXPayUtil.mapToXml(map));
        } catch (Exception e) {
            return "";
        }
    }


    private static String prePay(String paramXml) {
        return HttpUtils.postXML("https://api.mch.weixin.qq.com/pay/unifiedorder", paramXml);
    }

    private static String preRefund(String paramXml) {
        return HttpUtils.postXML("https://api.mch.weixin.qq.com/secapi/pay/refund", paramXml);
    }

    public static Map<String, String> miniProgramPayParams(String xml) throws Exception {
        Map<String, String> map = WXPayUtil.xmlToMap(xml);
        if (map.get("return_code").equals("FAIL") || map.get("result_code").equals("FAIL")) {
            throw new RuntimeException("支付失败");
        }
        Map<String, String> params = new HashMap<>();
        params.put("appId", map.get("appid"));
        params.put("nonceStr", map.get("nonce_str"));
        params.put("package", "prepay_id=" + map.get("prepay_id"));
        params.put("signType", "MD5");
        params.put("timeStamp", String.valueOf(System.currentTimeMillis()));
        String paySign = WXPayUtil.generateSignature(params, KEY);
        params.put("paySign", paySign);
        return params;
    }

    /**
     * 验证签名
     */
    public static boolean checkSign(Map<String, String> map) throws Exception {
        String sign = map.get("sign");
        map.remove("sign");
        String signValue = WXPayUtil.generateSignature(map, KEY);
        return signValue.equals(sign);
    }


    /**
     * 解析微信服务器发来的请求
     *
     * @param inputStream
     * @return 微信返回的参数集合
     */
    @SuppressWarnings("unchecked")
    public static Map<String, String> parseXml(InputStream inputStream) {
        SortedMap<String, String> map = new TreeMap<String, String>();
        try {
            // 获取request输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素所有节点
            List<Element> elementList = root.elements();
            // 遍历所有子节点
            for (Element element : elementList) {
                map.put(element.getName(), element.getText());
            }
            // 释放资源
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

}
